#include <string>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <assert.h>
#include <ctime>
#include "TASK.hpp"
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

#define processNUM 5
vector<task_t> tasks;

class channel
{
public:
    channel(int filefd, pid_t id, string &name) : _filefd(filefd), _id(id), _ProcessName(name)
    {
    }

public:
    int _filefd;
    pid_t _id;
    string _ProcessName;
};

void selver()
{
    while (true)
    {
        int cmdcode = 0;
        int n = read(0, &cmdcode, sizeof(int));

        if (n == sizeof(int))
        {
            cout << "slaver say@ get a command: " << getpid() << " cmdcode: " << cmdcode << endl;
            // 执行任务
            if (cmdcode >= 0 && cmdcode < tasks.size())
            {
                cout << "hehaehae" << endl;
                tasks[cmdcode]();
            }
        }

        if (n == 0)
        {
            break;
        }
    }
}

// test
void DebugTest(const vector<channel> &channels)
{
    for (const auto &c : channels)
    {
        cout << c._filefd << " " << c._id << " " << c._ProcessName << endl;
    }
}

void ProcessPoolInit(vector<channel> *channels)
{
    vector<int> oldfds;
    for (int i = 0; i < processNUM; i++)
    {
        int pipefd[2];
        int n = pipe(pipefd);
        assert(!n);

        pid_t id = fork();
        if (id == 0)
        {
            for (vector<int>::iterator it = oldfds.begin(); it != oldfds.end(); it++)
            {
                cout << "child :" << getpid() << " close history :" << *it;
                close(*it);
            }
            cout << "\n";
            close(pipefd[1]);
            // 0号文件描述符之指向管道输入描述符
            dup2(pipefd[0], 0);
            selver();
            close(pipefd[0]);
            cout << "process : " << getpid() << " quit" << std::endl;
            exit(0);
        }

        close(pipefd[0]);

        std::string name = "process-" + std::to_string(i);
        channels->push_back(channel(pipefd[1], id, name));
        oldfds.push_back(pipefd[1]);

        sleep(1);
    }
}

void ctrselver(vector<channel> &channels)
{

    int cnt = 10;
    while (cnt--)
    {

        // 获得任务码
        int cmdcode = rand() % tasks.size();

        // 选择进程
        int process = rand() % channels.size();

        cout << "father say : comcode:" << cmdcode << "alread  sendto " << channels[process]._filefd << " name :"
             << channels[process]._ProcessName << endl;

        write(channels[process]._filefd, &cmdcode, sizeof(cmdcode));

        sleep(1);
    }
}

void closeselver(const vector<channel> &channels)
{
    // for (auto &c : channels)
    // {
    //     close(c._filefd);
    // }
    // for (auto &c : channels)
    // {
    //     waitpid(c._id, NULL, 0);
    // }

    for (auto &c : channels)
    {
        close(c._filefd);
        waitpid(c._id, NULL, 0);
    }

    // int last = channels.size() - 1;
    // for (int i = last; i >= 0; i--)
    // {
    //     close(channels[i]._filefd);
    //     waitpid(channels[i]._id, NULL, 0);
    // }
}
void test1()
{
    vector<channel> channels;
    ProcessPoolInit(&channels);
    DebugTest(channels);

    srand(time(NULL));

    LoadTask(&tasks);

    ctrselver(channels);

    closeselver(channels);
}
int main()
{
    test1();
    sleep(2);
    return 0;
}
